﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;

namespace FileHandling
{
    public struct record
    {
        public int recordnumber;
        public string isdeleted;
        public string ad;
        public string soyad;
        public int yas;
    }


    public class MySettings
    {

       
        public record oku;
        public static int TotalRecord { get; set; }
        private static FileStream file;
        private const int maxRecordLength = 110;
        private static ArrayList deletedRecords = new ArrayList();
        static MySettings()
        {
            TotalRecord = getTotalRecord();
        }

        public static int getTotalRecord()
        {
            
            try
            {
                file = new FileStream(SettingsFile, FileMode.Open); 
            }
            catch (IOException e)
            {
                
                return 0;
            }

            int totalRecords =(int) file.Length / maxRecordLength;//Dosyanın kaç byte tan oluştuğunu öğren ve 
                                                        //kaç kayıt olduğunu bulmak için toplam kayıt 
                                                        //sayısı bölü bir kayıtın uzunluğu.

            closeStream(); //Streami kapat.

            return totalRecords;
        }

        private static void closeStream()
        {
            file.Close();
        }
        public static void Save(record tofile, int no = -1)
        {
            if (!File.Exists(SettingsFile))
            {
                file = File.Create(SettingsFile);
            }else{
                file = File.Open(SettingsFile, FileMode.Append);
            } //Dosya yoksa newRecord bir dosya oluşturur eğer var ise ekleme modunda dosya açılır. 
 
            if (deletedRecords.Count != 0 && no == -1) 
            {
                closeStream();
                file = File.Open(SettingsFile, FileMode.Open);
                file.Position = findPosition( (int) deletedRecords[0]);
                tofile.recordnumber = ((int)deletedRecords[0]);
                deletedRecords.RemoveAt(0);
                TotalRecord--;
            }
            else if (no != -1)
            {
                closeStream();
                file = File.Open(SettingsFile, FileMode.Open);
                file.Position = findPosition(no);
                TotalRecord--;
            }

            string recordString = buildRecordString(tofile);
            byte[] bytesToSave = StrToByteArray(recordString);//FileStream byte yazıp byte
                                                              //okuduğu için string i byte dizisine dönüştürmeliyiz.

            file.Write(bytesToSave, 0, bytesToSave.Length);  //Burada byte dizisinin hangi eleman aralığı 
                                                             //yazılacak onu söylüyoruz.
            closeStream();
            TotalRecord++;
            

        }
        /*Stringi byte dizisi olarak geri döndürür.
         */
        public static byte[] StrToByteArray(string str)
        {
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
            return encoding.GetBytes(str);
        }
        /*Bu method dosyaya yazılacak stringi oluşturur.
         * Herbir kayıtta kayıt numarası için 6 karakter,
         * silinip silinmediğini belirten 4 karakter
         * ad için 45 karakter,
         * soyad için 45 karakter,
         * ve yas içinde 6 karakter yer vardır.
         * ve bunların arasında 4 tanede : karakteri vardır.
         * Bir kayıt toplam 110 karakter uzunluğundadır(110byte)
         */
        private static string buildRecordString(record toFile)
        {
            StringBuilder stringBuilder = new StringBuilder();
            
            stringBuilder.Append(Convert.ToString(toFile.recordnumber).PadRight(6));
            stringBuilder.Append(':');

            stringBuilder.Append(toFile.isdeleted);
            stringBuilder.Append(':');

            stringBuilder.Append(toFile.ad.PadRight(45));
            stringBuilder.Append(':');

            stringBuilder.Append(toFile.soyad.PadRight(45));
            stringBuilder.Append(':');

            stringBuilder.Append(Convert.ToString(toFile.yas).PadRight(6));
            


            return stringBuilder.ToString();
        }

        private static void removeWhiteSpaces(string[] record)
        {
            for (int i = 0; i < record.Length; i++)
            {
                record[i] = record[i].Trim();
            }
        }

        public static string[] Load(int no)
        {
            if (no > TotalRecord || no < 1)
                return null;
            try
            {
                file = File.OpenRead(SettingsFile);
            }
            catch (IOException)
            {
                return null;
            }

            //Okumak için pozisyonun hesaplanması
            long position = findPosition(no);

           //fileStream istenilen pozisyona getirilir.
            file.Position = position;

           //110 byte okunur.

            byte[] bytesOfRecord = new byte[110];
            file.Read(bytesOfRecord, 0, 110);

            //Bytelar stringe çevirilir.

            string record = ByteArrayToStr(bytesOfRecord);
            string[] parsedRecord = record.Split(':');
            removeWhiteSpaces(parsedRecord);
            closeStream();
            return (parsedRecord[1] == "0xFF") ? parsedRecord : null;

        }

        private static long findPosition(int no)
        {
            return (no - 1) * 110;
        }

        public static string ByteArrayToStr(byte[] bytes)
        {
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
            return encoding.GetString(bytes);
        }

        
        private static void changeStatus(string[] parsedRecord)
        {
            parsedRecord[1] = "0x00";
        }

        public static bool deleteRecord(int no)
        {
            if (no > TotalRecord || no < 1 || deletedRecords.Contains(no))
                return false;
            try
            {
                file = File.OpenRead(SettingsFile);
            }
            catch (IOException)
            {
                return false;
            }

            //Okumak için pozisyonun hesaplanması
            long position = findPosition(no);

            //fileStream istenilen pozisyona getirilir.
            file.Position = position;

            //110 byte okunur.
            //TODO aşağıdaki satırlar method haline getirilebilir.load methodundada tekrarlanmış.
            byte[] bytesOfRecord = new byte[110];
            file.Read(bytesOfRecord, 0, 110);

            //Bytelar stringe çevirilir.

            string record = ByteArrayToStr(bytesOfRecord);
            string[] parsedRecord = record.Split(':');
            removeWhiteSpaces(parsedRecord);

            changeStatus(parsedRecord);
            closeStream();
            Save(parsedRecordToRecord(parsedRecord), no);
            deletedRecords.Add(no);
            deletedRecords.Sort();
            return true ;
        }

        private static record parsedRecordToRecord(string[] parsedRecord)
        {
            record newRecord;
            newRecord.recordnumber = int.Parse(parsedRecord[0]);
            newRecord.isdeleted = parsedRecord[1];
            newRecord.ad = parsedRecord[2];
            newRecord.soyad = parsedRecord[3];
            newRecord.yas = int.Parse(parsedRecord[4]);
            return newRecord;
        }


        public static string[] ParseLine(string satir)
        {
            string[] words = satir.Split(':');
            return words;
        }



        private static string SettingsFolder
        {
            get
            {
                string folder = @"C:\Users\Serhat\Desktop\";
                if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
                return folder;
            }

        }

        private static string SettingsFile
        {
            get
            {
                return Path.Combine(SettingsFolder, "file.txt");
            }

        }




    }
}
